#ifndef STM32G4_SYS_H
#define STM32G4_SYS_H

#include "stm32g474xx.h" 
#include "main.h"
/*
Memory	Category 2	Category 3	Category 4
128KB	STM32G431	STM32G471
		STM32G441	STM32G473
					STM32G474
256KB				STM32G471
					STM32G473
					STM32G474
512KB				STM32G471	STM32G491
					STM32G473	STM32G4A1 (AES)
					STM32G474
					STM32G483
					STM32G484
*/
//位带操作 G4可能不行
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x48000014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x48000414
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x48000814
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x48000C14
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x48001014
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x48001414
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x48001814

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x48000010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x48000410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x48000810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x48000C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x48001010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x48001410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x48001810 
//位段操作，兼容位带的程序
typedef struct
{
	u32 i0:1;
	u32 i1:1;
	u32 i2:1;
	u32 i3:1;
	u32 i4:1;
	u32 i5:1;
	u32 i6:1;
	u32 i7:1;
	u32 i8:1;
	u32 i9:1;
	u32 i10:1;
	u32 i11:1;
	u32 i12:1;
	u32 i13:1;
	u32 i14:1;
	u32 i15:1;
	u32 ires:16;
	u32 o0:1;
	u32 o1:1;
	u32 o2:1;
	u32 o3:1;
	u32 o4:1;
	u32 o5:1;
	u32 o6:1;
	u32 o7:1;
	u32 o8:1;
	u32 o9:1;
	u32 o10:1;
	u32 o11:1;
	u32 o12:1;
	u32 o13:1;
	u32 o14:1;
	u32 o15:1;
	u32 ores:16;
} MGPIO;
#define PAout(n)   (*(MGPIO*)(GPIOA_IDR_Addr)).o##n  //输出 
#define PAin(n)    (*(MGPIO*)(GPIOA_IDR_Addr)).i##n //输入 
#define PBout(n)   (*(MGPIO*)(GPIOB_IDR_Addr)).o##n  //输出 
#define PBin(n)    (*(MGPIO*)(GPIOB_IDR_Addr)).i##n  //输入 
#define PCout(n)   (*(MGPIO*)(GPIOC_IDR_Addr)).o##n  //输出 
#define PCin(n)    (*(MGPIO*)(GPIOC_IDR_Addr)).i##n  //输入 
#define PDout(n)   (*(MGPIO*)(GPIOD_IDR_Addr)).o##n  //输出 
#define PDin(n)    (*(MGPIO*)(GPIOD_IDR_Addr)).i##n  //输入 
#define PEout(n)   (*(MGPIO*)(GPIOE_IDR_Addr)).o##n  //输出 
#define PEin(n)    (*(MGPIO*)(GPIOE_IDR_Addr)).i##n  //输入 
#define PFout(n)   (*(MGPIO*)(GPIOF_IDR_Addr)).o##n  //输出 
#define PFin(n)    (*(MGPIO*)(GPIOF_IDR_Addr)).i##n  //输入 
#define PGout(n)   (*(MGPIO*)(GPIOG_IDR_Addr)).o##n  //输出 
#define PGin(n)    (*(MGPIO*)(GPIOG_IDR_Addr)).i##n  //输入 
//兼容需要变量引脚号的情况
#define PortSet(p,n,o) p->BSRR=(1<<(n))<<((1-(o))*16) //低16位是1
#define PortGet(p,n) ((p->IDR & (1<<(n))) != 0)
#define PAset(n,o)	PortSet(GPIOA,n,o)
#define PAget(n)	PortGet(GPIOA,n)
#define PBset(n,o)	PortSet(GPIOB,n,o)
#define PBget(n)	PortGet(GPIOB,n)
#define PCset(n,o)	PortSet(GPIOC,n,o)
#define PCget(n)	PortGet(GPIOC,n)
#define PDset(n,o)	PortSet(GPIOD,n,o)
#define PDget(n)	PortGet(GPIOD,n)
#define PEset(n,o)	PortSet(GPIOE,n,o)
#define PEget(n)	PortGet(GPIOE,n)
#define PFset(n,o)	PortSet(GPIOF,n,o)
#define PFget(n)	PortGet(GPIOF,n)
#define PGset(n,o)	PortSet(GPIOG,n,o)
#define PGget(n)	PortGet(GPIOG,n)
////////////////////////////////////////////////////////////////////////////////// 
//Ex_NVIC_Config专用定义
#define GPIO_A 				0
#define GPIO_B 				1
#define GPIO_C				2
#define GPIO_D 				3
#define GPIO_E 				4
#define GPIO_F 				5
#define GPIO_G 				6 

#define FTIR   				1  		//下降沿触发
#define RTIR   				2  		//上升沿触发

//GPIO设置专用宏定义
#define GPIO_MODE_IN    	0		//普通输入模式
#define GPIO_MODE_OUT		1		//普通输出模式
#define GPIO_MODE_AF		2		//AF功能模式
#define GPIO_MODE_AIN		3		//模拟输入模式

#define  GPIO_SPEED_LOW      (0x00000000U)  //0 ~ 10 MHz
#define  GPIO_SPEED_MEDIUM   (0x00000001U)  //10 ~ 50 MHz
#define  GPIO_SPEED_HIGH     (0x00000002U)  //50 ~ 100 MHz
#define  GPIO_SPEED_VERYHIGH (0x00000003U)  //100 ~ 180 MHz

#define GPIO_PUPD_NONE		0		//不带上下拉
#define GPIO_PUPD_PU		1		//上拉
#define GPIO_PUPD_PD		2		//下拉
#define GPIO_PUPD_RES		3		//保留 

#define GPIO_OTYPE_PP		0		//推挽输出
#define GPIO_OTYPE_OD		1		//开漏输出 

//GPIO引脚编号定义
#define PIN0				(1<<0)
#define PIN1				(1<<1)
#define PIN2				(1<<2)
#define PIN3				(1<<3)
#define PIN4				(1<<4)
#define PIN5				(1<<5)
#define PIN6				(1<<6)
#define PIN7				(1<<7)
#define PIN8				(1<<8)
#define PIN9				(1<<9)
#define PIN10				(1<<10)
#define PIN11				(1<<11)
#define PIN12				(1<<12)
#define PIN13				(1<<13)
#define PIN14				(1<<14)
#define PIN15				(1<<15)

////////////////////////////////////////////////////////////////////////////////// 
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq);		//系统时钟设置
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq); //时钟初始化  
void Sys_Soft_Reset(void);      							//系统软复位
void Sys_Standby(void);         							//待机模式
void Sys_Shutdown(void);
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset);	//设置偏移地址
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group);			//设置NVIC分组
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group);//设置中断
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM);				//外部中断配置函数(只对GPIOA~I)
void GPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8 AFx);		//GPIO复用功能设置
void GPIO_Set(GPIO_TypeDef* GPIOx,u32 BITx,u32 MODE,u32 OTYPE,u32 OSPEED,u32 PUPD);//GPIO设置函数  
void wtd_ini(u8 div); //按默认0，200~600ms
void wtd_tri(void);
//以下为汇编函数
void WFI_SET(void);		//执行WFI指令
#define OS_OPEN_INT		__ASM volatile("cpsie i")//开启所有中断
#define OS_CLOSE_INT	__ASM volatile("cpsid i")//关闭所有中断
void switch_2_addr(u32 *pc); //切换到指定的程序指针
int flash_erase(void *pf); //擦MFLASH扇区,返回本扇区大小
int flash_write(u8 *p,int n,void *addr); //直接写入
int flash_eraseAwrite(u8 *p,int n,void *pf); //擦除并写入,输入数据指针，数据长度，MFLASH地址
//////////////////////////////////////////////////////////////////////////////

//系统变量
extern u32 SYS_task;
extern u16 SYS_idle;
extern u16 SYS_idle_dis;
extern vu32 SYS_time;

#define START_TASK(x)       SYS_task |= x

#define TASK_POOL_100			1	//周期任务

//#define TASK_                 //必须是2的幂次
void wait(vu32 i);
int void_putchar(int c);
extern int (*IO_putchar)(int);	//初始化的函数

#endif

